# -*- coding: utf-8 -*-
import math
import datetime
from exceptions import StandardError

import autocomplete_light

from django import forms
from django.forms.fields import EmailField
from django.forms.widgets import FileInput
from django.core.files.images import get_image_dimensions

from mdcssport.mdcsapp.models import Match, PointsLog, News, PlayerUserProfile
from mdcssport.mdcsapp.widgets import DateTimeWidget
from mdcssport.mdcsapp.result import Result
from django.forms.models import ModelMultipleChoiceField
from mdcsapp.models import MatchComment

"""
Widget koji nasledjuje SelectDateWidget i dodaje mu provere
"""
class SelectDateField(forms.Field):
    def clean(self, value):
        # proveravamo da vreme nije u buducnosti
        if (value == None):
            raise forms.ValidationError('Vreme mora da bude definisano')
        if value > datetime.datetime.now():
            raise forms.ValidationError('Vreme mora da bude u prošlosti')
        return value

"""
Field na formi koji sadrzi rezultat meca. Sluzi za validaciju unosa meca.
Vraca tuple (rezultat, winner)
"""
class ResultField(forms.Field):
    def clean(self, value):
        if not value:
            raise forms.ValidationError('Morate uneti rezultat')
        try:
            result = Result.parse_result(value)
            return result
        except StandardError as e:
            raise forms.ValidationError(e.args[0])

"""
Image field koji dozvoljava slike samo do 200x200 piksela
"""
class CustomSizeImage(forms.ImageField):
    def clean(self, data, initial=None):
        image = super(CustomSizeImage, self).clean(data, initial)
        w,h = get_image_dimensions(image)
        if w>200 and h>200:
            raise forms.ValidationError('Širina i visina slike moraju biti manji od 200 piksela')
        if w>200:
            raise forms.ValidationError('Širina slike mora biti manja od 200 piksela')
        if h>200:
            raise forms.ValidationError('Visina slike mora biti manja od 200 piksela')
        return image

"""
Email field koji dozvoljava da se ne unese nista
"""
class NonRequiredEmailField(EmailField):
    def clean(self, value):
        if value == None or value=='':
            return ''
        return super(EmailField, self).clean(value)

"""
Forma za unos meca. Koristi Match iz modela, ali ne prikazuje polje za pobednika jer se ono
automatski generise iz unesenog rezultata. Takodje koristi neku fancy kontrolu za unos datuma.
"""
class MatchForm(forms.ModelForm):
    date_played = SelectDateField(label='Vreme igranja', widget=DateTimeWidget())
    result = ResultField(label='Rezultat')
    home = ModelMultipleChoiceField(PlayerUserProfile.objects.all(),
                            widget=autocomplete_light.MultipleChoiceWidget(
                                'PlayerUserProfileAutocomplete'),
                            label="Prvi igrač")
    away = ModelMultipleChoiceField(PlayerUserProfile.objects.all(),
                            widget=autocomplete_light.MultipleChoiceWidget(
                                'PlayerUserProfileAutocomplete'),
                            label="Drugi igrač")
    class Meta:
        model = Match
        exclude = ('winner', 'date_generated')
  
    def clean(self):
        """
        Sluzi da proveri da li su uneti isti igraci. Stavljamo ovde jer clean ne zavisi od jednog,
        vec od dva polja.
        (http://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other)
        """
        cleaned_data = super(MatchForm, self).clean()
        home = cleaned_data.get('home')
        away = cleaned_data.get('away')
        game_type = cleaned_data.get('game_type')
        date_played = cleaned_data.get('date_played')
        result = cleaned_data.get('result')

        if not home or not away:
            raise forms.ValidationError('Morate uneti igrače')
        for user1 in home.all():
            for user2 in away.all():
                if user1.id == user2.id:
                    raise forms.ValidationError('Ne možete uneti meč u kome su igrali isti igrači na dve strane')

        if game_type == 1:
            if (home.all().count() != 1) or (away.all().count() != 1):
                raise forms.ValidationError('Šah može da igra samo jedan igrač na jednoj strani')
        elif game_type == 2:
            if home.all().count() != away.all().count():
                raise forms.ValidationError('Za stoni fudbal sa obe strane mora biti isti broj igrača')
            if (home.all().count() > 2):
                raise forms.ValidationError('Stoni fudbal može da igraju maksimalno po dva igrača na obe strane')
        elif game_type == 3:
            if math.fabs(home.all().count() - away.all().count()) > 1:
                raise forms.ValidationError('Razlika broja igrača na jednoj i na drugoj strani ne može biti veća od 1')
            if (home.all().count() < 4) or (away.all().count() < 4):
                raise forms.ValidationError('Fudbal može da igra minimalno 4 igrača na jednoj strani')
        elif game_type == 4:
            if (home.all().count() != away.all().count()):
                raise forms.ValidationError('Basket mora da igra isti broj igrača na obe strane')

        if result != None:
            result.is_valid(game_type)
        
        # proverimo da li postoji mec bilo kog od ova dva igraca koji je ispred njega vremenski
        for user in home.all():
            if date_played and PointsLog.objects.filter(user = user).filter(match__date_played__gte = date_played).count() > 0:
                raise forms.ValidationError('Igrač %s već ima odigranih mečeva posle ovoga' % user)
        for user in away.all():
            if date_played and PointsLog.objects.filter(user = user).filter(match__date_played__gte = date_played).count() > 0:
                raise forms.ValidationError('Igrač %s već ima odigranih mečeva posle ovoga' % user)
        return cleaned_data

class NewsForm(forms.ModelForm):
    class Meta:
        model = News
        exclude = ('date_updated', 'user')

class CommentForm(forms.ModelForm):
    class Meta:
        model = MatchComment
        exclude = ('date_created', 'date_updated', 'comment_author', 'match')

"""
Forma za user profile. Izbacuje sva polja koja se ne mogu menjati i dodaje polje email iz
Django klase user. Za slike se koristi poseban field koji dozvoljava samo slike do 200x200 piksela.
"""
class PlayerUserProfileForm(forms.ModelForm):
    email = NonRequiredEmailField(label='E-mail')
    image = CustomSizeImage(widget=FileInput())

    def __init__(self, *args, **kwargs):
        user = kwargs.get('instance')
        super(PlayerUserProfileForm, self).__init__(*args, **kwargs)
        self.fields['email'].initial = user.user.email

    def clean(self):
        cleaned_data = super(PlayerUserProfileForm, self).clean()
        #cleaned_data = self.cleaned_data
        send_mail = cleaned_data.get('send_mail')
        email = cleaned_data.get('email')
        if send_mail and email=='':
            raise forms.ValidationError('Ako želite da primate e-mail-ove, morate uneti e-mail adresu')
        return cleaned_data

    def save(self, force_insert=False, force_update=False, commit=True):
        user = super(PlayerUserProfileForm, self).save(commit)
        if user.send_mail:
            # menjamo mail samo ako je stiklirao da hoce da ga prima
            user.user.email = self.cleaned_data['email']
            user.user.save(force_insert=force_insert, force_update=force_update)
        if commit:
            user.save()
        return user

    class Meta:
        model = PlayerUserProfile
        exclude = ('user', 'chess_points', 'tf_points', 'football_points', 'basket_points', 'is_mdcs')

"""
Forma za odabir koji ce user-i da se pojave na strani. Logika polja je takva da je default = False
"""
class FilterUserForm(forms.Form):
    all_users = forms.BooleanField(label = "Prikaži i korisnike koji nisu igrali nijedan meč")
    not_only_mdcs = forms.BooleanField(label = "Prikaži i igrače van MDCS-a")
    not_active = forms.BooleanField(label = "Prikaži i neaktivne igrače")

"""
Forma za odabir vise usera
"""
class UserSelect(forms.Form):
    users = ModelMultipleChoiceField(PlayerUserProfile.objects.all(),
                            widget=autocomplete_light.MultipleChoiceWidget(
                                'PlayerUserProfileAutocomplete', widget_js_attributes={'max_values': 16}),
                            label="Odaberite igrače za prikaz")